package fr.umlv.escapeir.weapon;

import java.awt.Image;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.common.MathUtils;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;

import fr.umlv.escapeir.GameWorld;
import fr.umlv.escapeir.behavior.Behavior;
import fr.umlv.escapeir.behavior.Behaviors;
import fr.umlv.escapeir.behavior.LinearMove;
import fr.umlv.escapeir.game.WorldActor;
import fr.umlv.escapeir.painter.AnimatedWorldPainter;
import fr.umlv.escapeir.painter.ImageManager;
import fr.umlv.escapeir.painter.WorldGraphics2D;

class Fireball implements Weapon {

	private static final int IMAGE_PADDING = 20;
	private static final int SPEED = 100;
	private static final int LOADING_TIME = 10;

	private final Image image;
	private final GameWorld world;
	private final WorldActor actor;
	private final int groupIndex;
	
	private AnimatedWorldPainter painter;
	private float painterAngle = Float.MAX_VALUE;
	private Behavior behavior;
	private Body body;
	private float size;

	Fireball (final WorldActor actor, int groupIndex) {
		this.image = ImageManager.self().load("fireball.png");
		this.actor = actor;
		this.world = actor.getWorld();
		this.groupIndex = groupIndex;
		this.painter = new AnimatedWorldPainter() {
			private final int time = LOADING_TIME*GameWorld.STEP_PER_SECOND;
			private final float padding = 30f/time;
			private int tick;

			@Override
			public void apply() {
				painterAngle += 0.1;
				if (painterAngle > MathUtils.PI*2) painterAngle = 0;
				
				if (tick > time) return;
				++tick;
				size += padding;
				
			}
			@Override
			public void render(WorldGraphics2D painter) {
				painter.save();
				painter.translateFromWorld(getPosition());
				painter.rotate(getAngle());
				painter.drawRectWithImage(new Vec2(-size, size), new Vec2(size, -size), image);
				painter.restore();
			}
		};
		
		behavior = Behaviors.INERTIA;
	}

	@Override
	public void render(WorldGraphics2D painter) {
		this.painter.render(painter);
	}

	@Override
	public void apply() {
		behavior.apply();
		painter.apply();
	}

	@Override
	public void touch(WorldActor actor) {
		world.destroyActor(this);
		world.destroyBody(body);
	}

	@Override
	public Type getType() {
		return Type.WEAPON;
	}
	
	@Override
	public boolean fire(float theta) {
		BodyDef bdef = new BodyDef();
		bdef.type = BodyType.DYNAMIC;
		bdef.position.set(getPosition());
		bdef.userData = this;
		bdef.angle = theta;
		
		CircleShape shape = new CircleShape();
		shape.m_p.setZero();
		shape.m_radius = size;
		
		FixtureDef fdef = new FixtureDef();
		fdef.restitution = 0;
		fdef.density = 0;
		fdef.shape = shape;
		fdef.isSensor = true;
		fdef.filter.groupIndex = groupIndex;
		
		body = world.addSingleBodiedActor(this, bdef);
		body.createFixture(fdef);
		
		behavior = new LinearMove(body, theta, SPEED);
		return true;
	}

	@Override
	public Vec2 getPosition() {
		if (body != null) return new Vec2(body.getPosition());
		Vec2 pos = new Vec2(actor.getPosition());
		pos.y += size+IMAGE_PADDING;
		return pos;
	}

	@Override
	public float getAngle() {
		if (body != null) return body.getAngle();
		return painterAngle;
	}

	@Override
	public GameWorld getWorld() {
		return world;
	}

}
